/*
 * 文件名:CSemaphore.cpp
 *
 * 	 功能描述:
 *  创建日期: 2010-12-24
 *  版本Ver0.01
 *  作者: huanying2000
 *  版权:copyright 2010 by the Camellia project 
 *  free software under the terms of the LGPL 2.1
 */

#include "CSemaphore.hpp"

CSemaphore::CSemaphore(key_t semkey)
{
    key = semkey;
}

CSemaphore::~CSemaphore()
{
    cout << "~CSemaphore()\n";
}

void CSemaphore::initSemaphore()
{
    if ((semid = semget(key, 1, IPC_CREAT | 0660)) == -1)
    {
        cerr << "initSemaphore failed!\n";
        exit(EXIT_FAILURE);
    }
}

void CSemaphore::rmSemaphore()
{
    if (semctl(semid, 0, IPC_RMID, 0) == -1)
        cerr << "remove semaphore error!\n";
    else
        cout << "remove semaphore success!\n";
}

void CSemaphore::setSemValue(int semVal)
{
    usem.val = semVal;
    if (semctl(semid, 0, SETVAL, usem) == -1)
    {
        cerr << "setSemValue failed!\n";
        exit(EXIT_FAILURE);
    }
}

int CSemaphore::getSemValue()
{
    int res;

    if ((res = semctl(semid, 0, GETVAL)) == -1)
    {
        cerr << "getSemValue error!\n";
        exit(EXIT_FAILURE);
    }

    return res;
}

int CSemaphore::getSemNCnt()
{
	int res;

	if ((res = semctl(semid, 0, GETNCNT)) == -1)
	{
		cerr << "getSemNCnt error:" << errno << " - " << strerror(errno) << "!\n";
		exit(EXIT_FAILURE);
	}

	return res;
}

bool CSemaphore::getSemStat()
{
	usem.buf = static_cast<semid_ds *>(malloc(sizeof(semid_ds)));

	if (-1 == semctl(semid, 0, IPC_STAT, usem))
	{
		cerr << "getSemStat error:" << errno << ':' << strerror(errno) << "!\n";
		return false;
	}

	cout << "===semaphore state===\n";
	//cout << usem.buf << '\n';
	cout << "sem_otime:" << usem.buf->sem_otime << '\n';
	cout << "sem_ctime:" << usem.buf->sem_ctime << '\n';
	cout << "sem_nsems:" << usem.buf->sem_nsems << '\n';
	cout << "===semaphore state===\n";

	if (usem.buf)
		free(usem.buf);

	return true;
}

bool CSemaphore::semaphoreP(int val)
{
    struct sembuf semBuf;

    semBuf.sem_num = 0;
    semBuf.sem_op = -val;
    semBuf.sem_flg = SEM_UNDO;

    if (semop(semid, &semBuf, IPC_SET) == -1)
    {
        cerr << "semaphoreP error!\n";
        return false;
    }

    return true;
}

bool CSemaphore::semaphoreV(int val)
{
    struct sembuf semBuf;

    semBuf.sem_num = 0;
    semBuf.sem_op = val;
    semBuf.sem_flg = SEM_UNDO;

    if (semop(semid, &semBuf, IPC_SET) == -1)
    {
        cerr << "semaphoreV error!\n";
        return false;
    }

    return true;
}
